/*
 * Copyright Hundsun Technologies Inc. All Rights Reserved.
 */

package checker

import (
	"context"

	"hundsun.com/hsl/hschain/common/config"
	"hundsun.com/hsl/hschain/common/log/logging"
	"hundsun.com/hsl/hschain/consensus/common"
	dposcomm "hundsun.com/hsl/hschain/consensus/impl/dpos/common"
	"hundsun.com/hsl/hschain/module/common/utils"
)

const (
	configParamBlockCheckInterval        = "blockCheckInterval"
	configParamPendingBlockPoolFetchSize = "pendingBlockPoolFetchSize"
)

// NewChecker 新建一个checker模块
func NewChecker(client *common.BaseClient) *DposChecker {
	c := &DposChecker{
		Client: client,
	}
	return c
}

// DposChecker dpos校验模块
type DposChecker struct {
	checker *Checker

	Config  *config.ModuleConfig
	Client  *common.BaseClient
	RootCtx context.Context
	Log     logging.Log
}

// Start 启动
func (c *DposChecker) Start(rootCtx context.Context, cfg *config.ModuleConfig, log logging.Log) {
	c.Config = cfg
	c.Log = log
	c.RootCtx, _ = context.WithCancel(rootCtx)

	blockCheckInterval := utils.GetIntConfigParameterValue(c.Config, configParamBlockCheckInterval, 0)
	if blockCheckInterval <= 0 {
		blockCheckInterval = 5
	}
	pendingBlockPoolFetchSize := utils.GetIntConfigParameterValue(c.Config, configParamPendingBlockPoolFetchSize, 0)
	if pendingBlockPoolFetchSize <= 0 {
		pendingBlockPoolFetchSize = 10
	}

	c.Log.Infof("blockCheckInterval:%d pendingBlockPoolFetchSize:%d", blockCheckInterval, pendingBlockPoolFetchSize)

	var genesisMiners = &dposcomm.SharedMiners{}
	genesisMiners.ReplaceAll(c.Client.GetCurrentMiners())

	c.checker = &Checker{
		module:                       c,
		lastAcceptedBlockRound:       0,
		lastAcceptedBlockRoundMiners: genesisMiners,
	}

	err := c.checker.Init(blockCheckInterval, pendingBlockPoolFetchSize)
	if err != nil {
		c.Log.Errorf("init checker failed, err: %s", err.Error())
		return
	}

	c.FetchAndCheckBlocks()
}

// FetchAndCheckBlocks 拉取验证模块
func (c *DposChecker) FetchAndCheckBlocks() {
	startedSignal := make(chan struct{})
	checkerCtx, _ := context.WithCancel(c.RootCtx)
	go c.Client.Run(checkerCtx, startedSignal)
	<-startedSignal
}
